/*
 * Copyright Aristool AG Switzerland
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); 
 * you may not use this file except in compliance with the License. 
 * You may obtain a copy of the License at 
 * 
 * http://www.apache.org/licenses/LICENSE-2.0 
 * 
 * Unless required by applicable law or agreed to in writing, software 
 * distributed under the License is distributed on an "AS IS" BASIS, 
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
 * See the License for the specific language governing permissions and 
 * limitations under the License.
 */

package org.opprua.dss.application;

import java.util.Iterator;
import java.util.Map;

import org.opprua.dss.data.Component;
import org.opprua.dss.data.EmbeddedRequest;
import org.opprua.dss.data.MaskDescription;
import org.opprua.dss.data.MaskEntry;
import org.opprua.dss.data.RequiredData;
import org.opprua.tidy.beans.BeanField;
import org.opprua.tidy.beans.BeanHandler;
import org.opprua.tidy.util.Primitives;
import org.opprua.tidy.util.XReader;
import org.w3c.dom.Element;

/**
 * TODO: add Java doc
 * 
 * Prepared for first commit: 23.02.2007
 * 
 * @author Lin Li
 */
public class DComponent extends XReader {

  private DConfigData configData;
  private DAccess[] daccess;
  private DData[] ddata;
  private String descriptor;

  @Override
  public void read(Element e) {
    configData = collectOne(e, "configData", DConfigData.class);
    daccess = collect(e, "access", DAccess.class);
    ddata = collect(e, "data", DData.class);
    descriptor = null;
  }

  private String prepare(DApplication app) {

    RequiredData[] cdata = new RequiredData[ddata.length];
    for (int i = 0; i < cdata.length; i++) {
      String as = ddata[i].getAs();
      if (as.length() == 0) {
        as = ddata[i].getName();
      }
      cdata[i] = new RequiredData(ddata[i].getName(), as);
    }

    EmbeddedRequest[] creq = new EmbeddedRequest[daccess.length];
    for (int i = 0; i < creq.length; i++) {
      String name = daccess[i].getEntry();
      DEntry entry = app.getEntry(name);
      if(entry == null) {
        throw new Error("no such entry defined: " + name);
      }
      creq[i] = new EmbeddedRequest(daccess[i].getEntry(), daccess[i].getComponent(), daccess[i]
                  .getWithUpdates(), getMask(entry.getType(), name));
    }

    Component c = new Component(cdata, creq, getName(), getDojoRequire(), getDecorator());
    return BeanHandler.toJSON(c);
  }

  private MaskDescription getMask(Class<?> t, String name) {
    MaskDescription d = new MaskDescription();
    if(t == null) return d;
    d.setName(name);
    Map<String, BeanField> m = BeanField.getFields(t);
    for (Iterator<String> iter = m.keySet().iterator(); iter.hasNext();) {
      String k = iter.next();
      BeanField f = m.get(k);

      if (Primitives.getFor(f.getType()) != null || f.getType().equals(String.class)) {
        d.addEntryItem(new MaskEntry(f.getName(), f.getType().getName()));
      } else {
        d.addSubmaskItem(getMask(f.getType(), k));
      }
    }
    return d;
  }

  public String getName() {
    return getAttribute("name");
  }

  public String getDecorator() {
    return getAttribute("decorator");
  }

  public String getDojoRequire() {
    return getAttribute("dojoRequire");
  }

  public DConfigData getConfigData() {
    return configData;
  }

  public DAccess[] getAccess() {
    return daccess;
  }

  public DData[] getData() {
    return ddata;
  }

  public String getDescriptor(DApplication app) {
    if(descriptor == null) {
      descriptor = prepare(app);
    }
    return descriptor;
  }
}
